package com.jyh.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyh.blog.dao.RoleDao;
import com.jyh.blog.dto.RoleDTO;
import com.jyh.blog.dto.UserRoleDTO;
import com.jyh.blog.entity.Role;
import com.jyh.blog.entity.RoleMenu;
import com.jyh.blog.entity.RoleResource;
import com.jyh.blog.entity.UserRole;
import com.jyh.blog.exception.MyException;
import com.jyh.blog.handler.FilterInvocationSecurityMetadataSourceImpl;
import com.jyh.blog.service.RoleMenuService;
import com.jyh.blog.service.RoleResourceService;
import com.jyh.blog.service.RoleService;
import com.jyh.blog.service.UserRoleService;
import com.jyh.blog.utils.BeanCopyUtils;
import com.jyh.blog.vo.ConditionVO;
import com.jyh.blog.vo.RoleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.jyh.blog.constant.CommonConst.FALSE;

/**
 * (Role)表服务实现类
 *
 * @author jyh
 * @since 2023-02-14 13:41:48
 */
@Service("roleService")
public class RoleServiceImpl extends ServiceImpl<RoleDao, Role> implements RoleService {
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private RoleResourceService roleResourceService;
    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private FilterInvocationSecurityMetadataSourceImpl filterInvocationSecurityMetadataSource;

    @Override
    public List<UserRoleDTO> getUserRoleList() {
        List<Role> roleList = this.list();
        return BeanCopyUtils.copyList(roleList, UserRoleDTO.class);
    }

    @Override
    public List<RoleDTO> roleList(ConditionVO conditionVO) {
        return roleDao.roleList(conditionVO.getKeywords());
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdateRole(RoleVO roleVO) {
        //角色是否重名
        Role hasRole = this.getOne(new LambdaQueryWrapper<Role>().eq(Role::getName, roleVO.getName()));
        if (Objects.nonNull(hasRole) && ! hasRole.getId().equals(roleVO.getId())) {
            throw new MyException("角色名已存在");
        }
        //构建role
        Role role = Role.builder()
                .id(roleVO.getId())
                .name(roleVO.getName())
                .label(roleVO.getLabel())
                .isDisable(FALSE)
                .build();
        this.saveOrUpdate(role);
        //添加资源
        if (Objects.nonNull(roleVO.getResourceIdList())) {
            if (Objects.nonNull(roleVO.getId())) {
                //有角色id说明修改，需要删除角色以前的资源
                roleResourceService.remove(new LambdaQueryWrapper<RoleResource>()
                        .eq(RoleResource::getRoleId, roleVO.getId()));
            }
            //新建则构建后直接添加
            List<RoleResource> resourceList = roleVO.getResourceIdList().stream()
                    .map(id -> RoleResource.builder()
                            .roleId(role.getId())
                            .resourceId(id)
                            .build()
                    ).collect(Collectors.toList());
            //有角色id的话会删除记录，所以不存在更新
            roleResourceService.saveBatch(resourceList);
            //刷新角色资源
            filterInvocationSecurityMetadataSource.clearDataSource();

        }
        //添加菜单
        if (Objects.nonNull(roleVO.getMenuIdList())) {
            if (Objects.nonNull(roleVO.getId())) {
                //修改，需删除角色原来的菜单
                roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>()
                        .eq(RoleMenu::getRoleId, roleVO.getId()));
            }
            List<RoleMenu> menuList = roleVO.getMenuIdList().stream()
                    .map(id -> RoleMenu.builder()
                            .roleId(role.getId())
                            .menuId(id)
                            .build()
                    ).collect(Collectors.toList());
            roleMenuService.saveBatch(menuList);
        }
    }

    @Override
    public void deleteRoles(List<Integer> idList) {
        //有用户使用，不能删除
        int count = userRoleService.count(new LambdaQueryWrapper<UserRole>()
                .in(UserRole::getRoleId, idList));
        if(count>0){
            throw new MyException("有用户使用角色，不能删除");
        }
        //删除角色
        this.removeByIds(idList);
        //删除该角色的资源和菜单
        roleResourceService.remove(new LambdaQueryWrapper<RoleResource>().in(RoleResource::getRoleId,idList));
        roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>().in(RoleMenu::getRoleId,idList));
    }
}

